import java.io.*;

/**
 * @author Elite Bank
 */
public class ATMPacket {
	// Message parameter types
	public static final int	INT_LOWER			= 0x00;
	public static final int	INT_UPPER			= 0x4f;
	public static final int	STR_LOWER			= 0x50;
	public static final int	STR_UPPER			= 0x9f;

	// Packets with one int 0x00 - 0x4f
	// sends login accountnumber
	public static final int	INT_ACCOUNT_NUMBER	= 0x01;
	// sends login password
	public static final int	INT_PASS_CODE		= 0x02;
	// sends
	public static final int	INT_CONTAINER		= 0x30;
	// Tells client to display the message corresponding to that number
	public static final int	INT_DISP_SWITCH		= 0x31;
	// Tells client to display this int
	public static final int	INT_DISP_NUMBER		= 0x32;

	// Packets with one string 0x50 - 0x9f
	public static final int	STR_CONTAINER		= 0x50;
	public static final int	STR_NEW_LANG		= 0x51;

	// Packets without parameter 0xa0 - 0xff
	public static final int	CMD_OK				= 0xb0;
	public static final int	CMD_NOK				= 0xb1;
	public static final int	REQUEST_SHUTDOWN	= 0xc0;
	public static final int	REQUEST_INT			= 0xd0;
	public static final int	REQUEST_LANG		= 0xd1;

	private int				packetType;
	private int				intData;
	private String			strData;

	/**
	 * Constructor for int packets.
	 */
	public ATMPacket(int packetType, int intData) {
		if (!(packetType >= INT_LOWER && packetType <= INT_UPPER))
			System.err.printf("Packet type does not match input! (0x%2X)\n", packetType);
		this.packetType = packetType;
		this.intData = intData;
	}

	/**
	 * Constructor for string packets.
	 */
	public ATMPacket(int packetType, String stringData) {
		if (!(packetType >= STR_LOWER && packetType <= STR_UPPER))
			System.err.printf("Packet type does not match input! (0x%2X)\n", packetType);
		this.packetType = packetType;
		this.strData = stringData;
	}

	/**
	 * Constructor for packets without parameter.
	 */
	public ATMPacket(int packetType) {
		this.packetType = packetType;
	}

	/**
	 * Returns the packet type as an int in the range 0x00 - 0xff
	 */
	public int getPacketType() {
		return packetType;
	}

	/**
	 * Returns the data int.
	 */
	public int getIntData() {
		if (intData == Integer.MIN_VALUE)
			System.err.println("An null int is returned, possible error!");
		return intData;
	}

	/**
	 * Returns the data string.
	 */
	public String getStrData() {
		if (strData == null)
			System.err.println("An null string is returned, possible error!");
		return strData;
	}

	/**
	 * Writes ATMPacket to a stream.
	 */
	public void writeOut(DataOutputStream out) throws IOException {
		out.write((byte) this.packetType & 0xff);
		if ((this.packetType >= INT_LOWER) && (packetType <= INT_UPPER))
			out.writeInt(this.intData);
		else if (packetType >= STR_LOWER && packetType <= STR_UPPER)
			out.writeUTF(this.strData);
	}

	/**
	 * Reads from a stream and returns a ATMPacket.
	 */
	public static ATMPacket readIn(DataInputStream in) throws IOException,
			ClassNotFoundException {
		// Read messagetype
		int packetType = in.read();

		int intData = 0;
		String strData = "";

		// The range specifies parameter type
		if (packetType >= INT_LOWER && packetType <= INT_UPPER) {
			intData = in.readInt();
			// Return new packet
			return new ATMPacket(packetType, intData);
		} else if (packetType >= STR_LOWER && packetType <= STR_UPPER) {
			strData = in.readUTF();
			// Return new packet
			return new ATMPacket(packetType, strData);
		} else {
			// Return new packet
			return new ATMPacket(packetType);
		}

	}
}
